package com.adam.springbucks.unit;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class TaskFive implements CommandLineRunner {

	//定义公共常量
	static int COUNT=20;
	static int START=50;
	static int END=80;


	@Autowired
	RedisTemplate redisTemplate ;

	@Override
	public void run(String... args) throws Exception {

		// 1.实现分数升序或降序排名
		numberSort();

		// 2.实现全局 ID 生成（incr）
		String key = "id:generator:customer";
		long id = GUID(key);
		log.info("GUID is {}",id);

		// 3.基于 Bitmap 实现 id 去重
		removeDuplicateEntries();

		// 4.基于 HyperLogLog 实现剔除计数
		hyperLogLog();
	}

	/**
	 * 实现分数升序或降序排名
	 */
	private void numberSort() {
		String key = "sortKey";

		redisTemplate.delete(key);

		for (int i = 0; i < COUNT; i++) {
			redisTemplate.boundZSetOps(key).add("a" + i, getRandom(START, END));
		}

		// asc升序排名
		log.info("number asc {}", redisTemplate.boundZSetOps(key).range(0, -1));
		// desc降序排名
		log.info("number desc {}", redisTemplate.boundZSetOps(key).reverseRange(0, -1));
	}

	/**
	 *
	 * @param key
	 * @return
	 */
	private long GUID(String key) {
		 //清除key(也可以设置实现时间)
		 redisTemplate.delete(key);
		 return redisTemplate.opsForValue().increment(key,2);
	}

	/**
	 * 基于 HyperLogLog 实现剔除计数
	 */
	private void hyperLogLog() {
		List<Integer> list = new ArrayList<Integer>();
		//初始化数据
		for(int i = 0; i < COUNT; i++){
			list.add(getRandom(START, END));
		}

		String key ="hllList";
		//清除key
		redisTemplate.delete(key);
		redisTemplate.opsForHyperLogLog().add(key, list.toArray());
		log.info("list info {}",list);
		//剔重后统计数量
		log.info("count {}",redisTemplate.opsForHyperLogLog().size(key));
	}

	/**
	 * 基于 Bitmap 实现 id 去重
	 * 只适用id为整数
	 */
	private void removeDuplicateEntries() {
		List<Integer> oldList = new ArrayList<Integer>();
		//初始化数据
		for(int i = 0; i < 10; i++){
			oldList.add(getRandom(START, END));
		}
		//剔除前的list
		log.info("oldList {}",oldList);

		List<Integer> newList = new ArrayList<Integer>();
		//定义key名称
		String key="bitset";
		//清除key
		redisTemplate.delete(key);

		for(Integer o:oldList) {
			ValueOperations aa = redisTemplate.opsForValue();
			//判断key的o偏移量的值是否为1，如果返回true，
			boolean temp = redisTemplate.opsForValue().getBit(key, o);
			if(temp) {//为true说明以o为偏移量的值存在，不重复加入
				continue;
			}
			newList.add(o);
			//key键对应的值的value对应的ascii码，在o的位置变为1(true)
			redisTemplate.opsForValue().setBit(key, o, true);

		}
		//剔除后的list
		log.info("newList {}",newList);
	}

	/**
	 * 获取两个整数间的随机数
	 * @param start
	 * @param end
	 * @return
	 */
	private int getRandom(int start, int end){
		return (int)(Math.random() * (end-start+1) + start);
	}
}
